package com.cyanite.playlv2;

import com.cyanite.playlv2.util.NotificationsUtil;
import com.cyanite.playlv2.widget.SegmentedButton;
import com.cyanite.playlv2.widget.UserTripsAdapter;
import com.cyanite.playlv2.widget.SegmentedButton.OnClickListenerSegmentedButton;
import com.cyanite.playlv2api.types.Group;
import com.cyanite.playlv2api.types.Response;
import com.cyanite.playlv2api.types.Trip;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListView;

public class UserTripsActivity extends Activity{

    public static final String EXTRA_USER_ID = PlayLv2.PACKAGE_NAME
        + ".UserTripsActivity.EXTRA_USER_ID";

    private StateHolder mStateHolder;
    private ListView mListView;
    private ProgressDialog mProgressDialog;
    private LinearLayout mEmpty;
    private View mViewProgressBar;

    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    public void onCreate(Bundle savedInstanceState)    {
        super.onCreate(savedInstanceState);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(PlayLv2.INTENT_ACTION_LOGGED_OUT));
        setContentView(R.layout.user_trips_activity);

        mStateHolder = new StateHolder();
        if (getIntent().hasExtra(EXTRA_USER_ID))   {
            mStateHolder.setViewUserId(getIntent().getExtras().getString(EXTRA_USER_ID));
        }   else {
            finish();
            return;
        }
        mStateHolder.setIsLoggedInUser(
                mStateHolder.getViewUserId().equals(((PlayLv2) getApplication()).getUserId()));

        ensureUi();
        mStateHolder.startUserTripsHistoryTask(this);
    }

    private void ensureUi(){

        mViewProgressBar = findViewById(R.id.UserTripsProgress);
        mViewProgressBar.setVisibility(View.VISIBLE);

        mEmpty = (LinearLayout) findViewById(R.id.llEmptyUserTrips);
        mListView = (ListView)findViewById(R.id.lvUserTrips);
        SegmentedButton headerButton = (SegmentedButton)findViewById(R.id.btnTripsSegmented);
        headerButton.addButtons(
                getString(R.string.trips_process_upcoming),
                getString(R.string.trips_process_ongoing),
                getString(R.string.trips_process_done));

        headerButton.setOnClickListener(new OnClickListenerSegmentedButton() {
            public void onClick(int index) {
                mStateHolder.setItemClicked(index);
                updateUi();
            }
        });
    }

    @Override
    public void onPause() {
        super.onPause();
        if (isFinishing()) {
            unregisterReceiver(mLoggedOutReceiver);
            mStateHolder.cancel();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    private UserTripsAdapter.ButtonRowClickHandler btnOnClickListener
                        = new UserTripsAdapter.ButtonRowClickHandler()  {
        @Override
        public void onButtonInfoClick(Trip trip) {
            Intent intent = new Intent(UserTripsActivity.this, TripDetailsActivity.class);
            trip.setUserId(mStateHolder.getViewUserId());
            intent.putExtra(TripDetailsActivity.EXTRA_TRIP_PARCEL, trip);
            startActivity(intent);
        }
        @Override
        public void onButtonDeleteClick(Trip trip) {
            mStateHolder.setTripDeleted(trip);
            mStateHolder.startDeleteTask(UserTripsActivity.this, trip.getId());
        }
    };

    private void updateUi() {
        Group<Trip> trips = getTripsInFolder();
        if (trips != null && trips.size() > 0) {
            mEmpty.setVisibility(View.GONE);
            UserTripsAdapter adapter = new UserTripsAdapter(
                    this,
                    ((PlayLv2) getApplication()).getRemoteResourceManager(),
                    btnOnClickListener,
                    mStateHolder.getIsLoggedInUser());
            adapter.setGroup(trips);
            mListView.setAdapter(adapter);
        } else {
            mListView.setAdapter(null);
            mEmpty.setVisibility(View.VISIBLE);
        }
    }

    private void removeTrip() {
        Group<Trip> trips = getTripsInFolder();
        if (trips != null  && trips.size() > 0) {
            trips.remove(mStateHolder.getTripDeleted());
        }
    }

    private Group<Trip> getTripsInFolder() {
        Group<Trip> trips = null;
        switch ( mStateHolder.getItemClicked() )   {
            case 0:
                trips = mStateHolder.getTripsUpcoming();
                break;
            case 1:
                trips = mStateHolder.getTripsOngoing();
                break;
            case 2:
                trips = mStateHolder.getTripsDone();
                break;
        }
        return trips;
    }


    private void onTaskStart() {
        mViewProgressBar.setVisibility(View.VISIBLE);
    }

    private void onDeleteTaskComplete(Response response, Exception ex) {
        dismissProgressDialog();
        if (response != null && response.getValue().equals("0")) {
            removeTrip();
            updateUi();
        } else if (ex != null) {
            NotificationsUtil.ToastReasonForFailure(this, ex);
        }
    }

    private static class TaskDeleteTrip extends AsyncTask<Void, Void, Response> {
        private UserTripsActivity mActivity;
        private String mTripId;
        private Exception mException;

        public TaskDeleteTrip(UserTripsActivity activity, String tripId) {
            mActivity = activity;
            mTripId = tripId;
        }

        @Override
        public Response doInBackground(Void... params) {
            try {
                Response response = ((PlayLv2) mActivity.getApplication()).getPlayLv2Api().deleteTrip(mTripId);
                if (response == null)   response = new Response();
                return response;
            } catch (Exception ex) {
                mException = ex;
                return null;
            }
        }

        @Override
        protected void onPreExecute() {
            mActivity.showProgressDialog();
        }

        @Override
        public void onPostExecute(Response response) {
            if (mActivity != null) {
                mActivity.onDeleteTaskComplete(response, mException);
            }
        }
    }

    private void onTaskComplete(Group<Trip> trips, Exception ex) {
        mViewProgressBar.setVisibility(View.GONE);
        if (trips != null && trips.size() > 0) {
            mEmpty.setVisibility(View.GONE);
            for (Trip it : trips) {
                if (it.getProcess() > 0) mStateHolder.getTripsOngoing().add(it);
                else if (it.getProcess() == 0) mStateHolder.getTripsDone().add(it);
                else if (it.getProcess() < 0) mStateHolder.getTripsUpcoming().add(it);
            }
            updateUi();
        } else if (ex != null) {
            NotificationsUtil.ToastReasonForFailure(this, ex);
        }   else {
            mEmpty.setVisibility(View.VISIBLE);
        }
    }

    private static class TaskTrips extends AsyncTask<Void, Void, Group<Trip>> {

        private PlayLv2 mPlayLv2;
        private UserTripsActivity mActivity;
        private Exception mException;
        private String mViewUserId;

        public TaskTrips(UserTripsActivity activity, String viewUserId) {
            mPlayLv2 = ((PlayLv2) activity.getApplication());
            mActivity = activity;
            mViewUserId = viewUserId;
        }

        @Override
        public Group<Trip> doInBackground(Void... params) {
            try {
                return mPlayLv2.getPlayLv2Api().trips(mViewUserId, "0");
            } catch (Exception ex) {
                mException = ex;
                return null;
            }
        }

        @Override
        protected void onPreExecute() {
            mActivity.onTaskStart();
        }

        @Override
        public void onPostExecute(Group<Trip> trips) {
            if (mActivity != null) {
                mActivity.onTaskComplete(trips, mException);
            }
        }
    }

    private ProgressDialog showProgressDialog() {
        if (mProgressDialog == null) {
            ProgressDialog dialog = new ProgressDialog(this);
            dialog.setMessage(getString(R.string.user_trips_activity_delete_progress_note));
            dialog.setIndeterminate(true);
            dialog.setCancelable(true);
            mProgressDialog = dialog;
        }
        mProgressDialog.show();
        return mProgressDialog;
    }

    private void dismissProgressDialog() {
        try {
            mProgressDialog.dismiss();
        } catch (IllegalArgumentException e) {
            // We don't mind. android cleared it for us.
        }
    }

    private static class StateHolder {
        private TaskTrips mTaskTrips;
        private TaskDeleteTrip mTaskDeleteTrip;
        private String mViewUserId;
        private Trip mTripDeleted;
        private Group<Trip> mTripsUpcoming;
        private Group<Trip> mTripsOngoing;
        private Group<Trip> mTripsDone;
        private boolean mIsLoggedInUser;
        private int mItemClicked;

        public StateHolder() {
            mIsLoggedInUser = false;
            mTripsUpcoming = new Group<Trip>();
            mTripsOngoing = new Group<Trip>();
            mTripsDone = new Group<Trip>();
        }

        public boolean getIsLoggedInUser() {
            return mIsLoggedInUser;
        }

        public void setIsLoggedInUser(boolean isLoggedInUser) {
            mIsLoggedInUser = isLoggedInUser;
        }

        int getItemClicked()   {
            return mItemClicked;
        }

        void setItemClicked(int index) {
            mItemClicked = index;
        }

        public void setTripDeleted(Trip trip){
            mTripDeleted = trip;
        }

        public Trip getTripDeleted(){
            return mTripDeleted;
        }

        public Group<Trip> getTripsUpcoming() {
            return mTripsUpcoming;
        }

        public Group<Trip> getTripsOngoing() {
            return mTripsOngoing;
        }

        public Group<Trip> getTripsDone() {
            return mTripsDone;
        }

        public void setViewUserId(String userId)    {
            mViewUserId = userId;
        }

        public String getViewUserId()   {
            return mViewUserId;
        }

        public void startUserTripsHistoryTask(UserTripsActivity activity) {
            mTaskTrips = new TaskTrips(activity, mViewUserId);
            mTaskTrips.execute();
        }

        public void startDeleteTask(UserTripsActivity activity, String tripId) {
            mTaskDeleteTrip = new TaskDeleteTrip(activity, tripId);
            mTaskDeleteTrip.execute();
        }

        public void cancel() {
            mTaskTrips.cancel(true);
        }
    }
}
